using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Konst3d.Efficiency;
using Konst3d.Efficiency.Suite;

namespace PEM
{
	internal partial class TasksViewModel: ViewModelBase
	{
		#region Types

		internal delegate void EventHandler(ViewModelBase sender);

		internal enum FilterType
		{
			All,
			Active,
			Completed,
			Failed
		}

		public enum SortingType
		{
			Title,
			Severity,
			State,
			Created,
			DeadLine,
			TimeLeft
		}

		#endregion // Types

		#region Events

		public event EventHandler SuiteOpened;
		public event EventHandler SuiteClosed;
		public event EventHandler SuiteCreated;
		public event EventHandler SuiteDeleted;
		public event EventHandler TaskSelected;
		public event EventHandler SelectedTaskStateChanged;

		#endregion // Events

		#region Properties

		public bool HasItems
		{
			get
			{
				return Suite != null ? Suite.Tasks.Count > 0 : false;
			}
		}

		public ObservableList2<ITask> Tasks
		{
			get;
			private set;
		}

		public IEnumerable<FilterType> Filters
		{
			get;
			private set;
		}

		public FilterType Filter
		{
			get
			{
				return _filter;
			}
			set
			{
				if (_filter != value)
				{
					_filter = value;
					UpdateTaskList();
				}
			}
		}

		public IEnumerable<SortingType> SortingOptions
		{
			get;
			private set;
		}

		public SortingType Sorting
		{
			get
			{
				return _sorting;
			}
			set
			{
				if (_sorting != value)
				{
					_sorting = value;
					UpdateTaskList();
				}
			}
		}

		public SortingDirection SortingDirection
		{
			get
			{
				return _sortingDirection;
			}
			set
			{
				if (value != _sortingDirection)
				{
					_sortingDirection = value;
					UpdateTaskList();
				}
			}
		}

		public ITask Selected
		{
			get
			{
				return _selected;
			}
			set
			{
				_selected = value;

				if (TaskSelected != null)
				{
					TaskSelected(this);
				}

				NotifyPropertyChanged("Selected");
			}
		}

		public CommandsCollection Commands
		{
			get;
			private set;
		}

		public IEfficiencySuite Suite
		{
			get
			{
				return _parentModel.Suite;
			}
		}

		#endregion // Properties

		#region Constructor

		public TasksViewModel(Window parentWindow, MainWindowViewModel parentModel)
		{
			Contract.Requires(parentWindow != null);
			Contract.Requires(parentModel  != null);

			_parentWindow = parentWindow;
			_parentModel = parentModel;

			_parentModel.SuiteOpened += OnSuiteOpened;
			_parentModel.SuiteClosed += OnSuiteClosed;
			_parentModel.SuiteCreated += OnSuiteCreated;
			_parentModel.SuiteDeleted += OnSuiteDeleted;


			_comparers.Add(SortingType.Title, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? String.Compare(x.Title, y.Title) : String.Compare(y.Title, x.Title);
			});
			_comparers.Add(SortingType.State, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? (int)x.State - (int)y.State : (int)y.State - (int)x.State;
			});
			_comparers.Add(SortingType.Severity, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? (int)x.Severity - (int)y.Severity : (int)y.Severity - (int)x.Severity;
			});
			_comparers.Add(SortingType.Created, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? DateTime.Compare(x.Created, y.Created) : DateTime.Compare(y.Created, x.Created);
			});
			_comparers.Add(SortingType.DeadLine, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? DateTime.Compare(x.DeadLine, y.DeadLine) : DateTime.Compare(y.DeadLine, x.DeadLine);
			});
			_comparers.Add(SortingType.TimeLeft, (ITask x, ITask y) => {
				return _sortingDirection == SortingDirection.Ascending ? TimeSpan.Compare(x.TimeLeft, y.TimeLeft) : TimeSpan.Compare(y.TimeLeft, x.TimeLeft);
			});

			Filters = new FilterType[] { FilterType.All, FilterType.Active, FilterType.Completed, FilterType.Failed };
			SortingOptions = new SortingType[] { SortingType.Title, SortingType.State, SortingType.Severity, SortingType.TimeLeft, SortingType.Created, SortingType.DeadLine };
			Tasks = new ObservableList2<ITask>();
			Commands = new CommandsCollection(this);

			_createEditTaskDlg = new CreateEditTaskDialog();
		}

		#endregion // Constructor

		#region Overriden Methods

		protected override void DisposeManaged()
		{
			base.DisposeManaged();

			_createEditTaskDlg.Close();
			_createEditTaskDlg = null;

			_parentModel.SuiteOpened -= OnSuiteOpened;
			_parentModel.SuiteClosed -= OnSuiteClosed;
			_parentModel.SuiteCreated -= OnSuiteCreated;
			_parentModel.SuiteDeleted -= OnSuiteDeleted;
			_parentModel = null;

			Tasks.Clear();
		}

		#endregion // Overriden Methods

		#region Event Handlers

		private void OnSuiteOpened(MainWindowViewModel sender)
		{
			UpdateTaskList();

			if (SuiteOpened != null)
			{
				SuiteOpened(this);
			}
		}

		private void OnSuiteClosed(MainWindowViewModel sender)
		{
			UpdateTaskList();

			if (SuiteClosed != null)
			{
				SuiteClosed(this);
			}
		}

		private void OnSuiteCreated(MainWindowViewModel sender)
		{
			UpdateTaskList();

			if (SuiteCreated != null)
			{
				SuiteCreated(this);
			}
		}

		private void OnSuiteDeleted(MainWindowViewModel sender)
		{
			UpdateTaskList();

			if (SuiteDeleted != null)
			{
				SuiteDeleted(this);
			}
		}

		#endregion // Event Handlers

		#region Private Methods

		private void UpdateTaskList()
		{
			Tasks.BeginUpdate();
			Tasks.Clear();

			if (Suite != null)
			{
				foreach (var task in Suite.Tasks)
				{
					if (IsTaskMutches(task, _filter))
					{
						Tasks.Add(task);
					}
				}

				Tasks.Sort(_comparers[_sorting]);
			}

			Tasks.EndUpdate();

			// NotifyPropertyChanged("HasItems");
		}

		private static bool IsTaskMutches(ITask task, FilterType filter)
		{
			Contract.Requires(task != null);

			bool matches = false;

			switch (filter)
			{
				case FilterType.All:
					matches = true;
					break;

				case FilterType.Active:
					matches = task.State == TaskState.Active;
					break;

				case FilterType.Completed:
					matches = task.State == TaskState.Completed;
					break;

				case FilterType.Failed:
					matches = task.State == TaskState.Failed;
					break;
			}

			return matches;
		}

		#endregion // Private Methods

		#region Fields

		private Window _parentWindow;
		private MainWindowViewModel _parentModel;
		private FilterType _filter = FilterType.All;
		private SortingType _sorting = SortingType.Title;
		private SortingDirection _sortingDirection = SortingDirection.Ascending;
		private ITask _selected;
		private CreateEditTaskDialog _createEditTaskDlg;
		private Dictionary<SortingType, Comparison<ITask>> _comparers = new Dictionary<SortingType, Comparison<ITask>>();

		#endregion // Fields
	}
}
